Core Image
概要
静止画/動画を高パフォーマンスでリアルタイムに処理/解析するための API を提供する Framework。GPU で処理を行う場合に利用される OpenGL や、CPU で並列処理する場合に利用される Grand Central Dispatch などに対する抽象化レイヤーと捉えることもできる。
静止画であれば Core Graphics、動画であれば Core Video、その他様々な形式で入力されてきた画像に対して、フィルタ を加えることで処理を行う。フィルタでは、ぼかしを加えたり、色調を変えたり、コントラストを整えたり.. さらには画像のリサイズやクロップなども行える。built-in のフィルタが数多く存在するため、基本的には用意されたフィルタをそのまま適用するだけで、簡単に画像に効果を加えることができる。
フィルタは非巡回有効グラフを形成することができる (フィルタグラフ)。つまり、あるフィルタの出力が別のフィルタの入力になり、その出力がまた別のフィルタの入力に... といったように、複数のフィルタを重ね掛けすることができるようになっている。複数のフィルタを組み合わせることで、最終的に複雑な効果を画像に加えることができる。
その他にも、バーコードの生成や、顔認識をはじめとする特徴解析、カスタムフィルタのパッケージング/配布機能なども持ち合わせている。このうち、特徴解析については Vision Framework という後発の Framework もになっている。
https://developer.apple.com/documentation/coreimage
Core Image Programming Guide
概念
カーネル
画像処理分野において、画像になんらかの変換を加える場合には カーネル (フィルタ) と呼ばれる行列が利用されることがほとんどなのだという。Core Image でもこのカーネルを利用してフィルタを記述することができる。
https://en.wikipedia.org/wiki/Kernel_(image_processing)
CIKernel
Core Image におけるフィルターの核となるのは CIKernel である。built-in で用意されたものもあるし、自作することもできる。
現在 Core Image でカーネルの記述に使えるのは、Core Image Kernel Language と Metal Shading Language であり、前者は deprecated で後者が推奨されている。CIKernel を利用することで Core Image にカーネルを読み込ませることができる。読み込んだ後、Core Image はカーネルの関数を組み合わせて咲いてきたしたプログラムをビルドした上で、それを利用する。
Core Image は効率化のため、可能な限り処理を遅延させ、最後に接続されたフィルタの出力が要求されて初めて処理を実行する。
Writing Custom Kernels
Core Image Filter Reference
Processing an Image Using Built-in Filters
CIFilter
最終的な画像を生成するのに利用する、mutable な軽量オブジェクト。入力画像に加えて、複数のパラメータを受け取ることが可能になっている。
https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html
CIImage
CIImage は Core Image において画像を表現するデータだけれど、ビットマップデータは保持しておらず、画像をどのように処理するか?という情報のみを保持している。画像それ自体ではなく、画像を生成するためのレシピのようなもの、という捉え方もできる。最終的に UIImage のような描画可能なフォーマットに変換されるタイミングで、全てのフィルタを適用してビットマップデータを生成する。
CIContext
CIContext は、CPU あるいは GPU を利用してフィルターのコンパイルと実行を行う責務を持つ。これは必要なメモリを事前に確保するためのメモリプールのような役割を持っている。context の確保はコストが高いため、基本的には処理の前に一度だけ行い、処理中はそれを使い回す。イミュータブルであるため、スレッドセーフに利用できる。
使い方
1. CIContext を用意する
2. CIImage を用意する
3. CIFilter を用意して順次適用する
4. 最終的な出力の CIImage を CIContext で描画する
CGImage へ変換とか
GPU を使う別の context へ出力して GPU 経由で描画とか
code:swift
import CoreImage
let context = CIContext()
let filter = CIFilter(name: "CISepiaTone")!
filter.setValue(0.8, forKey: kCIInputIntensityKey)
let image = CIImage(contentsOfURL: myUrl)
filter.setValue(image, forKey: kCIInputImageKey)
let result = filter.outputImage!
let cgImage = context.createCGImage(result, from: result.extent)
https://www.objc.io/issues/21-camera-and-photos/core-image-intro/
CIContext
CIContext クラスは、CIImage を実際のピクセルデータとしてレンダリングしたり、顔/バーコード認識等の解析処理を担う。CIImage
https://www.hackingwithswift.com/books/ios-swiftui/basic-image-filtering-using-core-image
パフォーマンス問題
CPU/GPU 間でバッファを移動させるのはコストが高い
1方向への移動に止める
可能であれば GPU で完結させる
https://www.objc.io/issues/23-video/core-image-video/#cpuvsgpu
読んでおく...
https://stackoverflow.com/questions/51922595/confusion-about-cicontext-opengl-and-metal-swift-does-cicontext-use-cpu-or-g